package moduloRemoto.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import moduloRemoto.dao.interfaces.ServerLocal;

import org.hibernate.Hibernate;

@Stateless
public class ServerDao implements ServerLocal
{
	@PersistenceContext(unitName="DevManager.JPA.pu")
	protected EntityManager emanager;

	public <T> T find(final Class<T> cls, Serializable id) throws Exception
	{
		assert(cls != null);

		T o = emanager.find(cls, id);
		
		emanager.flush();
		
		return o;
	}

	public Object find(final String hql, final Map<String, Object> params, boolean isNamedQuery) throws Exception
	{
		Query q = isNamedQuery ? emanager.createNamedQuery(hql) : emanager.createQuery(hql);
		
		if (params != null && !params.isEmpty())
		{
			for (String param : params.keySet())
				q.setParameter(param, params.get(param));
		}
		
		return q.getSingleResult();
	}

	public <T> T insert(T obj) throws Exception
	{
		return persistPOJO(obj);
	}

	public <T> List<T> insert(List<T> lst) throws Exception
	{
		for (Object obj : lst)
			this.insert(obj);

		return lst;
	}

	public <T> T update(T obj) throws Exception
	{
		obj = emanager.merge(obj);
		
		emanager.flush();
		
		return obj;
	}

	public <T> void remove(List<T> lst) throws Exception
	{
		for (Object obj : lst)
			this.remove(obj);
	}

	public void remove(final Object obj) throws Exception
	{
		if (!emanager.contains(obj))
		{
			Object attachedObj = (Object) emanager.merge(obj);
			emanager.remove(attachedObj);
		}
		else
			emanager.remove(obj);
		
		emanager.flush();
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> executeQuery(String query) throws Exception
	{
		Query qry = emanager.createQuery(query);
		
		return (List<T>)qry.getResultList();
	}


	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	private <T> T persistPOJO(T entity) throws Exception
	{
		if (!Hibernate.isInitialized(entity))
			entity = emanager.merge(entity);
		
		emanager.persist(entity);
		emanager.flush();
		
		return entity;
	}
}